﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using LuaInterface;
using System;

namespace PengLuaKit
{
    //
    // @toLua interface
    //
    public class toLuaManager : MonoBehaviour
    {
        private static toLuaManager mInstance = null;

        [NoToLua]
        public static toLuaManager Instance
        {
             get
            {
                return mInstance;
            }
        }
        private LuaState lua;
        private LuaLooper loop = null;

        [NoToLua]
        public Action OnLuaPrepareWellHandler;

        [NoToLua]
        void Awake()
        {
            mInstance = this;

            lua = new LuaState();
            LoadCommonLibs();
            lua.LuaSetTop(0);

            LuaBinder.Bind(lua);
            LuaCoroutine.Register(lua, this);
        }

        [NoToLua]
        void LoadCommonLibs()
        {
            lua.OpenLibs(LuaDLL.luaopen_pb);
            lua.OpenLibs(LuaDLL.luaopen_lpeg);
            lua.OpenLibs(LuaDLL.luaopen_bit);
            lua.OpenLibs(LuaDLL.luaopen_socket_core);

            //
            lua.LuaGetField(LuaIndexes.LUA_REGISTRYINDEX, "_LOADED");
            lua.OpenLibs(LuaDLL.luaopen_cjson);
            lua.LuaSetField(-2, "cjson");

            lua.OpenLibs(LuaDLL.luaopen_cjson_safe);
            lua.LuaSetField(-2, "cjson.safe");
        }

        // Use this for initialization
        [NoToLua]
        void Start()
        {
            // todo: when in publish env, this path will change
#if UNITY_EDITOR
            lua.AddSearchPath(Application.dataPath + "/PengLuaKit");
            lua.AddSearchPath(Application.dataPath + "/PengLuaKit/Lua");
            lua.AddSearchPath(Application.dataPath + "/ToLua/Lua");
#else
            lua.AddSearchPath(Application.persistentDataPath + "/PengLuaKit");
            lua.AddSearchPath(Application.persistentDataPath + "/PengLuaKit/Lua");
            lua.AddSearchPath(Application.persistentDataPath + "/ToLua/Lua");
#endif

            lua.Start();

            // start looper
            loop = gameObject.AddComponent<LuaLooper>();
            loop.luaState = lua;

            if (OnLuaPrepareWellHandler != null)
                OnLuaPrepareWellHandler();
        }

        #region lua load file, call lua function api

        [NoToLua]
        public void DoFile(string filename)
        {
            lua.DoFile(filename);
        }

        // Update is called once per frame
        public object[] CallFunction(string funcName, params object[] args)
        {
            LuaFunction func = lua.GetFunction(funcName);
            if (func != null)
            {
                return func.LazyCall(args);
            }
            return null;
        }

        [NoToLua]
        public LuaFunction GetFunction(string funcName)
        {
            return lua.GetFunction(funcName);
        }

#endregion

        public void LuaGC()
        {
            lua.LuaGC(LuaGCOptions.LUA_GCCOLLECT);
        }

        [NoToLua]
        void OnDestroy()
        {
			if(loop != null ) loop.Destroy();
            loop = null;

            lua.Dispose();
            lua = null;
        }

    }
}